package com.ctsi.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Dict;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctsi.common.util.Search;
import com.ctsi.core.common.entity.LoginUser;
import com.ctsi.core.common.enums.StatusType;
import com.ctsi.core.common.exception.MarsException;
import com.ctsi.core.common.util.$;
import com.ctsi.core.common.util.EnumUtil;
import com.ctsi.core.database.util.PageUtil;
import com.ctsi.core.web.enums.DataScopeTypeEnum;
import com.ctsi.system.constant.DictConstant;
import com.ctsi.system.dto.RoleDsReqDTO;
import com.ctsi.system.entity.Role;
import com.ctsi.system.entity.RoleDataScope;
import com.ctsi.system.enums.SystemExceptionEnum;
import com.ctsi.system.mapper.RoleMapper;
import com.ctsi.system.service.IOrgService;
import com.ctsi.system.service.IRoleDataScopeService;
import com.ctsi.system.service.IRoleService;
import com.ctsi.system.service.IUserRoleService;
import com.ctsi.system.strategy.DataScopeContext;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统角色表 服务实现类
 * </p>
 *
 * @author wang xiao xiang
 */
@Service
@AllArgsConstructor
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {

	private final IUserRoleService userRoleService;
	private final IRoleDataScopeService roleDataScopeService;
	private final IOrgService orgService;
	private final DataScopeContext dataScopeContext;

	@Override
	public IPage<Role> listPage(Search search) {
		boolean isKeyword = $.isNotNull(search.getKeyword());
		LambdaQueryWrapper<Role> queryWrapper = Wrappers.<Role>query().lambda()
				// 根据名称查询
				.like(isKeyword, Role::getName, search.getKeyword())
				.or(isKeyword)
				// 根据惟一编码查询
				.like(isKeyword, Role::getCode, search.getKeyword())
				.orderByAsc(Role::getSort);
		return this.baseMapper.selectPage(PageUtil.getPage(search), queryWrapper);
	}

	@Override
	public List<Dict> getLoginRoles(Long userId,Integer userType) throws MarsException {
		List<Dict> dictList = CollectionUtil.newArrayList();
		// 获取用户角色id集合
		List<Long> roleIdList = userRoleService.getUserRoleIdList(userId,userType);
		if ($.isEmpty(roleIdList)) {
			return CollectionUtil.newArrayList();
		}
		// 根据角色id集合查询并返回结果
		this.list(Wrappers.<Role>query().lambda()
				.in(Role::getId, roleIdList)
				.eq(Role::getStatus, StatusType.ENABLE.getCode())).forEach(role -> {
			Dict dict = Dict.create();
			dict.put(DictConstant.ID, role.getId());
			dict.put(DictConstant.CODE, role.getCode());
			dict.put(DictConstant.NAME, role.getName());
			dictList.add(dict);
		});
		return dictList;
	}

	@Override
	public List<Long> getUserDataScopeIdList(List<Long> roleIdList, Long orgId) {
		Set<Long> resultList = CollectionUtil.newHashSet();

		//定义角色中最大数据范围的类型，目前系统按最大范围策略来，如果你同时拥有ALL和SELF的权限，系统最后按ALL返回
		Integer strongerDataScopeType = DataScopeTypeEnum.SELF.getCode();

		//获取用户自定义数据范围的角色集合
		List<Long> customDataScopeRoleIdList = CollectionUtil.newArrayList();

		if ($.isNotEmpty(roleIdList)) {
			List<Role> sysRoleList = this.listByIds(roleIdList);
			for (Role role : sysRoleList) {
				if (DataScopeTypeEnum.DEFINE.getCode().equals(role.getDataScopeType())) {
					customDataScopeRoleIdList.add(role.getId());
				} else {
					if (role.getDataScopeType() <= strongerDataScopeType) {
						strongerDataScopeType = role.getDataScopeType();
					}
				}
			}
		}

		//自定义数据范围的角色对应的数据范围
		List<Long> roleDataScopeIdList = roleDataScopeService.list(Wrappers.<RoleDataScope>query().lambda()
				.eq(RoleDataScope::getRoleId, customDataScopeRoleIdList))
				.stream().map(RoleDataScope::getOrgId).collect(Collectors.toList());

		//角色中拥有最大数据范围类型的数据范围
		List<Long> dataScopeIdList = orgService.getDataScopeListByDataScopeType(strongerDataScopeType, orgId);

		resultList.addAll(dataScopeIdList);
		resultList.addAll(roleDataScopeIdList);

		return CollectionUtil.newArrayList(resultList);
	}

	@Override
	public List<String> getDataScope(String id) {
		if ($.isEmpty(id)) {
			throw new MarsException(SystemExceptionEnum.ROLE_NOT_EXIST);
		}
		return roleDataScopeService.getRoleDataScope($.toLongList(id));
	}

	@Override
	public boolean setDataScope(LoginUser loginUser, RoleDsReqDTO roleDsReq) {
		// 更新Role数据范围
		Role role = this.getById(roleDsReq.getId());
		role.setDataScopeType(roleDsReq.getDataScopeType());
		this.updateById(role);
		// 根据code获取对象
		Optional<DataScopeTypeEnum> optional = EnumUtil.getEnumObject(DataScopeTypeEnum.class, d -> d.getCode().equals(roleDsReq.getDataScopeType()));
		DataScopeTypeEnum dataScopeTypeEnum = optional.orElse(null);
		if ($.isEmpty(dataScopeTypeEnum)) {
			throw new MarsException(SystemExceptionEnum.DATA_SCOPE_TYPE_ENUM_IS_EMPTY);
		}
		// 根据 数据范围类型 和 勾选的组织ID， 重新计算全量的组织ID
		List<Long> orgIds = dataScopeContext.getOrgIdsForDataScope(roleDsReq.getOrgIdList(), dataScopeTypeEnum, loginUser.getId());
		if ($.isNotEmpty(orgIds)) {
			roleDsReq.setOrgIdList(orgIds);
		}
		// 插入roleDataScope数据
		return this.roleDataScopeService.setDataScope(roleDsReq);
	}
}